package com.bruce.storage.service;

import com.bruce.storage.config.StorageConfig;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@ConditionalOnProperty(name = "storage.type", havingValue = "obs")
public class OBSStorageService implements StorageService{

    private final ObsClient obsClient;

    public OBSStorageService(StorageConfig properties) {
        this.obsClient = new ObsClient( properties.getAccessKey(), properties.getSecretKey(), properties.getEndpoint());
    }

    @Override
    public void uploadFile(String bucketName, String contentId, String fileName, String referenceIds, MultipartFile file) {
        try {
            uploadFile(bucketName, contentId, fileName, referenceIds, file.getInputStream());
        } catch (IOException e) {
            log.error("Failed to transform file to inputStream : {}", e.getMessage());
        }
    }

    @Override
    public void uploadFile(String bucketName, String contentId, String fileName, String referenceIds, InputStream inputStream) {
        try {
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.addUserMetadata("name", fileName);
            metadata.addUserMetadata("reference_ids", referenceIds != null ? referenceIds : "-1");
            PutObjectResult putObjectResult = obsClient.putObject(bucketName, contentId, inputStream, metadata);
            log.info("upload file result: {}", putObjectResult.getEtag());
        } catch (ObsException e) {
            log.error("Failed to upload file to OBS", e);
        }
    }

    @Override
    public InputStream downloadFile(String bucketName, String contentId) {
        try {
            return obsClient.getObject(bucketName, contentId).getObjectContent();
        } catch (ObsException e) {
            log.error("Failed to download file from OBS", e);
            return null;
        }
    }

    @Override
    public void deleteFile(String bucketName, String fileName) {
        try {
            DeleteObjectResult deleteObjectResult = obsClient.deleteObject(bucketName, fileName);
            log.info("delete file result: {}", deleteObjectResult.getObjectKey());
        } catch (ObsException e) {
            log.error("Failed to delete file from OBS", e);
        }
    }

    @Override
    public void deleteFiles(String bucketName, List<String> fileNames) {
        DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest();
        deleteObjectsRequest.setBucketName(bucketName);
        fileNames.forEach(deleteObjectsRequest::addKeyAndVersion);
        try {
            DeleteObjectsResult deleteObjectsResult = obsClient.deleteObjects(deleteObjectsRequest);
            log.info("delete files result: {}", deleteObjectsResult.getDeletedObjectResults());
        } catch (ObsException e) {
            log.error("Failed to delete files from OBS", e);
        }
    }

    @Override
    public Map<String, Object> getMetadata(String bucketName, String contentId) {
        try {
            return obsClient.getObjectMetadata(bucketName, contentId).getAllMetadata();
        } catch (ObsException e) {
            log.error("Failed to get metadata from OBS", e);
            return null;
        }
    }
}
